package io.renren.common.utils;

import org.springframework.util.Base64Utils;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.*;
import java.util.Base64;
import java.util.Objects;
import java.util.UUID;

public final class Base64Util {



    /**
     * 本地图片转换Base64的方法
     *
     * @param imgPath
     */

    public static String ImageToBase64(String imgPath) {
        byte[] data = null;
        // 读取图片字节数组
        try {
            InputStream in = new FileInputStream(imgPath);
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 对字节数组Base64编码
        BASE64Encoder encoder = new BASE64Encoder();
        // 返回Base64编码过的字节数组字符串
        return encoder.encode(Objects.requireNonNull(data));
    }



    public  static MultipartFile base64ToMultipart(String imgStr){
        try {
            String [] baseStr = imgStr.split(",");
            BASE64Decoder base64Decoder = new BASE64Decoder();
            byte[] b =  new byte[0];
            b = base64Decoder.decodeBuffer(baseStr[1]);
            for(int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {
                    b[i] += 256;
                }
            }
            return  new BASE64DecodedMultipartFile(b,baseStr[0]) ;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }
    public  static MultipartFile base64ImgToMultipart(String imgStr){
        try {
            String [] baseStr = imgStr.split(",");
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] b =  new byte[0];
            b = decoder.decodeBuffer(baseStr[0]);
            for(int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {
                    b[i] += 256;
                }
            }
            return  new BASE64DecodedMultipartFile(b,baseStr[1]) ;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }


    //base64字符串转化成图片
    public static File base64ToFile(String base64) throws Exception {
        if(base64.contains("data:image")){
            base64 = base64.substring(base64.indexOf(",")+1);
        }
        base64 = base64.toString().replace("\r\n", "");
        //创建文件目录
        String prefix=".jpeg";
        File file = File.createTempFile(UUID.randomUUID().toString(), prefix);
        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        try {
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] bytes =  decoder.decodeBuffer(base64);
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(bytes);
        }finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return file;
    }


    /**
     * 输入流转为base64字符串
     *
     * @param in 输入流
     * @return base64字符串
     */
    public static String ioToBase64(InputStream in) {
        String strBase64 = "";
        ByteArrayOutputStream bs = new ByteArrayOutputStream();

        String ret;
        try {
            int index = 0;
            byte[] bytes = new byte[1024];

            while ((index = in.read(bytes)) != -1) {
                bs.write(bytes, 0, index);
            }

            byte[] bytes1 = bs.toByteArray();
            in.read(bytes1);
            strBase64 = (new BASE64Encoder()).encode(bytes1);
            return strBase64.replaceAll("[\\s*\t\n\r]","");
        } catch (Exception e) {
            e.printStackTrace();
            ret = strBase64;
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
                if (bs != null) {
                    bs.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
                return strBase64;
            }
        }
        return ret;
    }

    /**
     * BASE64解密
     *
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptBASE64(byte[] key) {
        try {
            return Base64Utils.decode(key);
        }catch (Exception e){
            return "".getBytes();
        }
    }

    /**
     * 精确计算base64字符串文件大小（单位：B）
     * @param base64String
     * @return
     */
    public static double base64FileSize(String base64String) {
        /**检测是否含有base64,文件头)*/
        if (base64String.lastIndexOf(",") > 0) {
            base64String = base64String.substring(base64String.lastIndexOf(",")+1);
        }
        /** 获取base64字符串长度(不含data:audio/wav;base64,文件头) */
        int size0 = base64String.length();
        /** 获取字符串的尾巴的最后10个字符，用于判断尾巴是否有等号，正常生成的base64文件'等号'不会超过4个 */
        String tail = base64String.substring(size0 - 10);
        /** 找到等号，把等号也去掉,(等号其实是空的意思,不能算在文件大小里面) */
        int equalIndex = tail.indexOf("=");
        if (equalIndex > 0) {
            size0 = size0 - (10 - equalIndex);
        }
        /** 计算后得到的文件流大小，单位为字节 */
        return size0 - ((double) size0 / 8) * 2;
    }

    /**
     * BASE64加密
     *
     * @param key
     * @return
     * @throws Exception
     */
    public static String encryptBASE64(byte[] key) {
        return new String(Base64Utils.encode(key));
    }



    /** 将文件转成base64 字符串
     *
     *  @param path * 文件路径
     *
     */
    public static String encodeBase64File(String path) throws Exception {
        File file = new File(path);
        FileInputStream inputFile = new FileInputStream(file);
        byte[] buffer = new byte[(int) file.length()];
        inputFile.read(buffer);
        inputFile.close();
        return new BASE64Encoder().encode(buffer);
    }

    /**
     * 将base64字符解码保存文件 *
     */
    public static void decoderBase64File(String base64Code, String targetPath) throws Exception {
        byte[] buffer = new BASE64Decoder().decodeBuffer(base64Code);
        FileOutputStream out = new FileOutputStream(targetPath);
        out.write(buffer);
        out.close();
    }

    /**
     * 将base64字符保存文本文件 *
     */
    public static void toFile(String base64Code, String targetPath) throws Exception {
        byte[] buffer = base64Code.getBytes();
        FileOutputStream out = new FileOutputStream(targetPath);
        out.write(buffer);
        out.close();
    }

    /**
     * java8 自带base64加密
     * @param data
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String javaBase64(String data) throws UnsupportedEncodingException {
        //编码
        String asB64 = Base64.getEncoder().encodeToString(data.getBytes("utf-8"));
        return asB64;
    }

    /**
     * java8 自带base64 解密
     * @param data
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String decoderJavaBase64(String data) throws UnsupportedEncodingException {
        //解码
        byte [] asBytes = Base64.getDecoder().decode(data);
        return new String(asBytes,"utf-8");
    }


    public static void main(String[] args) {
        try {
            //将文件转成base64 字符串
//            String base64Code = encodeBase64File("D:\\test\\test.sql");
//            System.out.println(base64Code);
//            decoderBase64File(base64Code, "D:解密.jpg");
            //将base64字符保存文本文件
//            toFile(base64Code, "D:\\hreetest.txt");
//            toFile(base64Code, "D:\\hreetest00.sql");
//            decoderBase64File(base64Code, "D:\\hree.sql");
            String a = javaBase64("nihao");
            String aa = javaBase64(a);
            System.out.println(aa);
            String b = decoderJavaBase64(aa);
            String bb = decoderJavaBase64(b);
            System.out.println(bb);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

